Import Packages

library(ggplot2)
library(plotly)
library(data.table)


Import Data and look at first couple records

setwd("F:/kaggle/Mercedes-Benz")
sample_submission <- fread("data/sample_submission.csv")
train <- fread("data/train.csv")
test <- fread("data/test.csv")
train[1:2,]
# 1 - ID
# 2 - Response Varuable (Time in Seconds on Test Stand)
# 3-10  String Option Codes
# 11-385 0/1 values based on option codes
# X7 and X9 are missinf for some reason.


Calculate Mean and SD for Response Variable (Y). This is the time (sec) for a vehicle on the MB test station.

mean(train[,y])
[1] 100.6693
sd(train[,y])
[1] 12.67938


Create plots for the Response Variable. Sorted by ID.

plot_ly(y=train$y, type="scatter")


Create plots for the Response Variable. Sorted by the Response Variable.

plot_ly(y=train[order(y),]$y, type="scatter")


Create histogram for the Response Variable.

 plot_ly(x=train$y, type="histogram")


Create histogram for the LOG(Response Variable).

 plot_ly(x=log(train$y), type="histogram")


Frequency tables for the first 10 variables (All with String Codes)

cbind(train[,.N,by=X0],Mean_Y=round(train[,mean(y),by=X0]$V1,1))[order(-N)]
cbind(train[,.N,by=X1],Mean_Y=round(train[,mean(y),by=X1]$V1,1))[order(-N)]
cbind(train[,.N,by=X2],Mean_Y=round(train[,mean(y),by=X2]$V1,1))[order(-N)]
cbind(train[,.N,by=X3],Mean_Y=round(train[,mean(y),by=X3]$V1,1))[order(-N)]
cbind(train[,.N,by=X4],Mean_Y=round(train[,mean(y),by=X4]$V1,1))[order(-N)]
cbind(train[,.N,by=X5],Mean_Y=round(train[,mean(y),by=X5]$V1,1))[order(-N)]
cbind(train[,.N,by=X6],Mean_Y=round(train[,mean(y),by=X6]$V1,1))[order(-N)]
cbind(train[,.N,by=X8],Mean_Y=round(train[,mean(y),by=X8]$V1,1))[order(-N)]#where is 7
#where is 9


Frequency plots for the first 10 variables (All with String Codes)

# column_names_for_option_plots_string_codes <- colnames(train)[3:5] #3:12
# for(i in column_names_for_option_plots_string_codes){
#   x_values <- as.data.frame(train[,.N,by=i][order(-N)])[,i]
#   y_values <- as.data.frame(train[,.N,by=i][order(-N)])[,'N']
#   plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar")
##Couldn't get loop plotting to work => https://github.com/ropensci/plotly/issues/273
#Plotting manually
column_names_for_option_plots_string_codes <- colnames(train)[3:10] #3:10
i<-1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)

i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)

i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)

i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)

i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)

i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)

i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)

i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)


Frequency table for the remaining variables (All with 0/1 Coding)

column_names_for_summary <- colnames(train)[11:length(colnames(train))]
Variable <- c()
N_0 <- c()
N_1 <- c()
Mean_0 <- c()
Mean_1 <- c()
for(i in column_names_for_summary){
  j<-1
  Variable <- c(Variable,i)
  N_0 <- c(N_0,train[,.N,by=i][1]$N)
  N_1 <- c(N_1,train[,.N,by=i][2]$N)
  Mean_0 <- c(Mean_0,round(train[,mean(y),by=i][1]$V1,1))
  Mean_1 <- c(Mean_1,round(train[,mean(y),by=i][2]$V1,1))
  j <- j+1
}
# N_0[is.na(N_0)==TRUE] <- 0
# N_1[is.na(N_1)==TRUE] <- 0
# Mean_0[is.na(Mean_0)==TRUE] <- 0
# Mean_1[is.na(Mean_1)==TRUE] <- 0
summary_results <- as.data.frame(cbind(Variable,N_0=N_0,N_1,Mean_0,Mean_1), stringsAsFactors = FALSE)
summary_results$N_0 <- as.integer(summary_results$N_0)
summary_results$N_1 <- as.integer(summary_results$N_1)
summary_results$Mean_0 <- as.numeric(summary_results$Mean_0)
summary_results$Mean_1 <- as.numeric(summary_results$Mean_1)
summary_results$Delta_Mean <- summary_results$Mean_1 - summary_results$Mean_0
summary_results


After Looking at Kaggle, checked for Duplicate fileds - Added Data to Frequency table for the remaining variables (All with 0/1 Coding).

train_2 <- train[, !duplicated(t(train))] #remove duplicated fields ... from raddar@Kaggle => https://www.kaggle.com/c/mercedes-benz-greener-manufacturing/discussion/34006
duplicate_column <- c()
for(i in duplicated(t(train))){
  duplicate_column <- c(duplicate_column,i)
}
duplicate_column <- duplicate_column[11:length(duplicate_column)]
summary_results$duplicate_column <- duplicate_column
summary_results_decreasing <- summary_results[order(-N_1),]
summary_results
summary_results_decreasing


List of Duplicated Columns

summary_results_decreasing[(summary_results_decreasing$duplicate_column==TRUE),]


LS0tDQp0aXRsZTogIk1lcmNlZGVzLUJlbnogRURBIE5vdGVib29rIg0KYXV0aG9yOiAiSmVmZiBIZWRiZXJnIg0KZGF0ZTogIjUtSnVuZS0yMDE3Ig0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KPGJyPg0KDQojIyMjIEltcG9ydCBQYWNrYWdlcw0KYGBge3IsbWVzc2FnZT1GQUxTRSx3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGRhdGEudGFibGUpDQpgYGANCg0KPGJyPg0KDQojIyMjICBJbXBvcnQgRGF0YSBhbmQgbG9vayBhdCBmaXJzdCBjb3VwbGUgcmVjb3Jkcw0KYGBge3J9DQpzZXR3ZCgiRjova2FnZ2xlL01lcmNlZGVzLUJlbnoiKQ0KDQpzYW1wbGVfc3VibWlzc2lvbiA8LSBmcmVhZCgiZGF0YS9zYW1wbGVfc3VibWlzc2lvbi5jc3YiKQ0KdHJhaW4gPC0gZnJlYWQoImRhdGEvdHJhaW4uY3N2IikNCnRlc3QgPC0gZnJlYWQoImRhdGEvdGVzdC5jc3YiKQ0KDQp0cmFpblsxOjIsXQ0KDQojIDEgLSBJRA0KIyAyIC0gUmVzcG9uc2UgVmFydWFibGUgKFRpbWUgaW4gU2Vjb25kcyBvbiBUZXN0IFN0YW5kKQ0KIyAzLTEwICBTdHJpbmcgT3B0aW9uIENvZGVzDQojIDExLTM4NSAwLzEgdmFsdWVzIGJhc2VkIG9uIG9wdGlvbiBjb2Rlcw0KDQojIFg3IGFuZCBYOSBhcmUgbWlzc2luZiBmb3Igc29tZSByZWFzb24uDQpgYGANCjxicj4NCg0KIyMjIyAgQ2FsY3VsYXRlIE1lYW4gYW5kIFNEIGZvciBSZXNwb25zZSBWYXJpYWJsZSAoWSkuICBUaGlzIGlzIHRoZSB0aW1lIChzZWMpIGZvciBhIHZlaGljbGUgb24gdGhlIE1CIHRlc3Qgc3RhdGlvbi4NCmBgYHtyfQ0KbWVhbih0cmFpblsseV0pDQpzZCh0cmFpblsseV0pDQpgYGANCjxicj4NCg0KIyMjIyAgQ3JlYXRlIHBsb3RzIGZvciB0aGUgUmVzcG9uc2UgVmFyaWFibGUuICBTb3J0ZWQgYnkgSUQuDQpgYGB7ciwgbWVzc2FnZT1GQUxTRX0NCnBsb3RfbHkoeT10cmFpbiR5LCB0eXBlPSJzY2F0dGVyIikNCmBgYA0KPGJyPg0KDQojIyMjICBDcmVhdGUgcGxvdHMgZm9yIHRoZSBSZXNwb25zZSBWYXJpYWJsZS4gIFNvcnRlZCBieSB0aGUgUmVzcG9uc2UgVmFyaWFibGUuDQpgYGB7ciwgbWVzc2FnZT1GQUxTRX0NCnBsb3RfbHkoeT10cmFpbltvcmRlcih5KSxdJHksIHR5cGU9InNjYXR0ZXIiKQ0KYGBgDQo8YnI+DQoNCiMjIyMgIENyZWF0ZSBoaXN0b2dyYW0gZm9yIHRoZSBSZXNwb25zZSBWYXJpYWJsZS4NCmBgYHtyfQ0KIHBsb3RfbHkoeD10cmFpbiR5LCB0eXBlPSJoaXN0b2dyYW0iKQ0KYGBgDQo8YnI+DQoNCiMjIyMgIENyZWF0ZSBoaXN0b2dyYW0gZm9yIHRoZSBMT0coUmVzcG9uc2UgVmFyaWFibGUpLg0KYGBge3J9DQogcGxvdF9seSh4PWxvZyh0cmFpbiR5KSwgdHlwZT0iaGlzdG9ncmFtIikNCmBgYA0KPGJyPg0KDQojIyMjICBGcmVxdWVuY3kgdGFibGVzIGZvciB0aGUgZmlyc3QgMTAgdmFyaWFibGVzIChBbGwgd2l0aCBTdHJpbmcgQ29kZXMpDQpgYGB7cn0NCmNiaW5kKHRyYWluWywuTixieT1YMF0sTWVhbl9ZPXJvdW5kKHRyYWluWyxtZWFuKHkpLGJ5PVgwXSRWMSwxKSlbb3JkZXIoLU4pXQ0KY2JpbmQodHJhaW5bLC5OLGJ5PVgxXSxNZWFuX1k9cm91bmQodHJhaW5bLG1lYW4oeSksYnk9WDFdJFYxLDEpKVtvcmRlcigtTildDQpjYmluZCh0cmFpblssLk4sYnk9WDJdLE1lYW5fWT1yb3VuZCh0cmFpblssbWVhbih5KSxieT1YMl0kVjEsMSkpW29yZGVyKC1OKV0NCmNiaW5kKHRyYWluWywuTixieT1YM10sTWVhbl9ZPXJvdW5kKHRyYWluWyxtZWFuKHkpLGJ5PVgzXSRWMSwxKSlbb3JkZXIoLU4pXQ0KY2JpbmQodHJhaW5bLC5OLGJ5PVg0XSxNZWFuX1k9cm91bmQodHJhaW5bLG1lYW4oeSksYnk9WDRdJFYxLDEpKVtvcmRlcigtTildDQpjYmluZCh0cmFpblssLk4sYnk9WDVdLE1lYW5fWT1yb3VuZCh0cmFpblssbWVhbih5KSxieT1YNV0kVjEsMSkpW29yZGVyKC1OKV0NCmNiaW5kKHRyYWluWywuTixieT1YNl0sTWVhbl9ZPXJvdW5kKHRyYWluWyxtZWFuKHkpLGJ5PVg2XSRWMSwxKSlbb3JkZXIoLU4pXQ0KY2JpbmQodHJhaW5bLC5OLGJ5PVg4XSxNZWFuX1k9cm91bmQodHJhaW5bLG1lYW4oeSksYnk9WDhdJFYxLDEpKVtvcmRlcigtTildI3doZXJlIGlzIDcNCiN3aGVyZSBpcyA5DQoNCmBgYA0KPGJyPg0KDQojIyMjICBGcmVxdWVuY3kgcGxvdHMgZm9yIHRoZSBmaXJzdCAxMCB2YXJpYWJsZXMgKEFsbCB3aXRoIFN0cmluZyBDb2RlcykNCmBgYHtyfQ0KIyBjb2x1bW5fbmFtZXNfZm9yX29wdGlvbl9wbG90c19zdHJpbmdfY29kZXMgPC0gY29sbmFtZXModHJhaW4pWzM6NV0gIzM6MTINCiMgZm9yKGkgaW4gY29sdW1uX25hbWVzX2Zvcl9vcHRpb25fcGxvdHNfc3RyaW5nX2NvZGVzKXsNCiMgICB4X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1pXVtvcmRlcigtTildKVssaV0NCiMgICB5X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1pXVtvcmRlcigtTildKVssJ04nXQ0KIyAgIHBsb3RfbHkoeD1hcy5saXN0KHhfdmFsdWVzKSx5PWFzLmxpc3QoeV92YWx1ZXMpLCB0eXBlPSJiYXIiKQ0KIyNDb3VsZG4ndCBnZXQgbG9vcCBwbG90dGluZyB0byB3b3JrID0+IGh0dHBzOi8vZ2l0aHViLmNvbS9yb3BlbnNjaS9wbG90bHkvaXNzdWVzLzI3Mw0KDQojUGxvdHRpbmcgbWFudWFsbHkNCmNvbHVtbl9uYW1lc19mb3Jfb3B0aW9uX3Bsb3RzX3N0cmluZ19jb2RlcyA8LSBjb2xuYW1lcyh0cmFpbilbMzoxMF0gIzM6MTANCmk8LTENCmN1cnJlbnRfY29sbmFtZSA8LSBjb2x1bW5fbmFtZXNfZm9yX29wdGlvbl9wbG90c19zdHJpbmdfY29kZXNbaV0NCnhfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLGN1cnJlbnRfY29sbmFtZV0NCnlfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLCdOJ10NCnBsb3RfbHkoeD1hcy5saXN0KHhfdmFsdWVzKSx5PWFzLmxpc3QoeV92YWx1ZXMpLCB0eXBlPSJiYXIiKSAlPiUgbGF5b3V0KHRpdGxlPWN1cnJlbnRfY29sbmFtZSkNCmk8LWkrMQ0KY3VycmVudF9jb2xuYW1lIDwtIGNvbHVtbl9uYW1lc19mb3Jfb3B0aW9uX3Bsb3RzX3N0cmluZ19jb2Rlc1tpXQ0KeF92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssY3VycmVudF9jb2xuYW1lXQ0KeV92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssJ04nXQ0KcGxvdF9seSh4PWFzLmxpc3QoeF92YWx1ZXMpLHk9YXMubGlzdCh5X3ZhbHVlcyksIHR5cGU9ImJhciIpICU+JSBsYXlvdXQodGl0bGU9Y3VycmVudF9jb2xuYW1lKQ0KaTwtaSsxDQpjdXJyZW50X2NvbG5hbWUgPC0gY29sdW1uX25hbWVzX2Zvcl9vcHRpb25fcGxvdHNfc3RyaW5nX2NvZGVzW2ldDQp4X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWyxjdXJyZW50X2NvbG5hbWVdDQp5X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWywnTiddDQpwbG90X2x5KHg9YXMubGlzdCh4X3ZhbHVlcykseT1hcy5saXN0KHlfdmFsdWVzKSwgdHlwZT0iYmFyIikgJT4lIGxheW91dCh0aXRsZT1jdXJyZW50X2NvbG5hbWUpDQppPC1pKzENCmN1cnJlbnRfY29sbmFtZSA8LSBjb2x1bW5fbmFtZXNfZm9yX29wdGlvbl9wbG90c19zdHJpbmdfY29kZXNbaV0NCnhfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLGN1cnJlbnRfY29sbmFtZV0NCnlfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLCdOJ10NCnBsb3RfbHkoeD1hcy5saXN0KHhfdmFsdWVzKSx5PWFzLmxpc3QoeV92YWx1ZXMpLCB0eXBlPSJiYXIiKSAlPiUgbGF5b3V0KHRpdGxlPWN1cnJlbnRfY29sbmFtZSkNCmk8LWkrMQ0KY3VycmVudF9jb2xuYW1lIDwtIGNvbHVtbl9uYW1lc19mb3Jfb3B0aW9uX3Bsb3RzX3N0cmluZ19jb2Rlc1tpXQ0KeF92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssY3VycmVudF9jb2xuYW1lXQ0KeV92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssJ04nXQ0KcGxvdF9seSh4PWFzLmxpc3QoeF92YWx1ZXMpLHk9YXMubGlzdCh5X3ZhbHVlcyksIHR5cGU9ImJhciIpICU+JSBsYXlvdXQodGl0bGU9Y3VycmVudF9jb2xuYW1lKQ0KaTwtaSsxDQpjdXJyZW50X2NvbG5hbWUgPC0gY29sdW1uX25hbWVzX2Zvcl9vcHRpb25fcGxvdHNfc3RyaW5nX2NvZGVzW2ldDQp4X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWyxjdXJyZW50X2NvbG5hbWVdDQp5X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWywnTiddDQpwbG90X2x5KHg9YXMubGlzdCh4X3ZhbHVlcykseT1hcy5saXN0KHlfdmFsdWVzKSwgdHlwZT0iYmFyIikgJT4lIGxheW91dCh0aXRsZT1jdXJyZW50X2NvbG5hbWUpDQppPC1pKzENCmN1cnJlbnRfY29sbmFtZSA8LSBjb2x1bW5fbmFtZXNfZm9yX29wdGlvbl9wbG90c19zdHJpbmdfY29kZXNbaV0NCnhfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLGN1cnJlbnRfY29sbmFtZV0NCnlfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLCdOJ10NCnBsb3RfbHkoeD1hcy5saXN0KHhfdmFsdWVzKSx5PWFzLmxpc3QoeV92YWx1ZXMpLCB0eXBlPSJiYXIiKSAlPiUgbGF5b3V0KHRpdGxlPWN1cnJlbnRfY29sbmFtZSkNCmk8LWkrMQ0KY3VycmVudF9jb2xuYW1lIDwtIGNvbHVtbl9uYW1lc19mb3Jfb3B0aW9uX3Bsb3RzX3N0cmluZ19jb2Rlc1tpXQ0KeF92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssY3VycmVudF9jb2xuYW1lXQ0KeV92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssJ04nXQ0KcGxvdF9seSh4PWFzLmxpc3QoeF92YWx1ZXMpLHk9YXMubGlzdCh5X3ZhbHVlcyksIHR5cGU9ImJhciIpICU+JSBsYXlvdXQodGl0bGU9Y3VycmVudF9jb2xuYW1lKQ0KDQpgYGANCjxicj4NCg0KIyMjIyAgRnJlcXVlbmN5IHRhYmxlIGZvciB0aGUgcmVtYWluaW5nIHZhcmlhYmxlcyAoQWxsIHdpdGggMC8xIENvZGluZykNCmBgYHtyfQ0KY29sdW1uX25hbWVzX2Zvcl9zdW1tYXJ5IDwtIGNvbG5hbWVzKHRyYWluKVsxMTpsZW5ndGgoY29sbmFtZXModHJhaW4pKV0NClZhcmlhYmxlIDwtIGMoKQ0KTl8wIDwtIGMoKQ0KTl8xIDwtIGMoKQ0KTWVhbl8wIDwtIGMoKQ0KTWVhbl8xIDwtIGMoKQ0KDQpmb3IoaSBpbiBjb2x1bW5fbmFtZXNfZm9yX3N1bW1hcnkpew0KICBqPC0xDQogIFZhcmlhYmxlIDwtIGMoVmFyaWFibGUsaSkNCiAgTl8wIDwtIGMoTl8wLHRyYWluWywuTixieT1pXVsxXSROKQ0KICBOXzEgPC0gYyhOXzEsdHJhaW5bLC5OLGJ5PWldWzJdJE4pDQogIE1lYW5fMCA8LSBjKE1lYW5fMCxyb3VuZCh0cmFpblssbWVhbih5KSxieT1pXVsxXSRWMSwxKSkNCiAgTWVhbl8xIDwtIGMoTWVhbl8xLHJvdW5kKHRyYWluWyxtZWFuKHkpLGJ5PWldWzJdJFYxLDEpKQ0KICBqIDwtIGorMQ0KfQ0KDQojIE5fMFtpcy5uYShOXzApPT1UUlVFXSA8LSAwDQojIE5fMVtpcy5uYShOXzEpPT1UUlVFXSA8LSAwDQojIE1lYW5fMFtpcy5uYShNZWFuXzApPT1UUlVFXSA8LSAwDQojIE1lYW5fMVtpcy5uYShNZWFuXzEpPT1UUlVFXSA8LSAwDQoNCnN1bW1hcnlfcmVzdWx0cyA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKFZhcmlhYmxlLE5fMD1OXzAsTl8xLE1lYW5fMCxNZWFuXzEpLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpzdW1tYXJ5X3Jlc3VsdHMkTl8wIDwtIGFzLmludGVnZXIoc3VtbWFyeV9yZXN1bHRzJE5fMCkNCnN1bW1hcnlfcmVzdWx0cyROXzEgPC0gYXMuaW50ZWdlcihzdW1tYXJ5X3Jlc3VsdHMkTl8xKQ0Kc3VtbWFyeV9yZXN1bHRzJE1lYW5fMCA8LSBhcy5udW1lcmljKHN1bW1hcnlfcmVzdWx0cyRNZWFuXzApDQpzdW1tYXJ5X3Jlc3VsdHMkTWVhbl8xIDwtIGFzLm51bWVyaWMoc3VtbWFyeV9yZXN1bHRzJE1lYW5fMSkNCnN1bW1hcnlfcmVzdWx0cyREZWx0YV9NZWFuIDwtIHN1bW1hcnlfcmVzdWx0cyRNZWFuXzEgLSBzdW1tYXJ5X3Jlc3VsdHMkTWVhbl8wDQpzdW1tYXJ5X3Jlc3VsdHMNCmBgYA0KPGJyPg0KDQojIyMjICBBZnRlciBMb29raW5nIGF0IEthZ2dsZSwgY2hlY2tlZCBmb3IgRHVwbGljYXRlIGZpbGVkcyAtIEFkZGVkIERhdGEgdG8gRnJlcXVlbmN5IHRhYmxlIGZvciB0aGUgcmVtYWluaW5nIHZhcmlhYmxlcyAoQWxsIHdpdGggMC8xIENvZGluZykuDQpgYGB7cn0NCnRyYWluXzIgPC0gdHJhaW5bLCAhZHVwbGljYXRlZCh0KHRyYWluKSldICNyZW1vdmUgZHVwbGljYXRlZCBmaWVsZHMgLi4uIGZyb20gcmFkZGFyQEthZ2dsZSA9PiBodHRwczovL3d3dy5rYWdnbGUuY29tL2MvbWVyY2VkZXMtYmVuei1ncmVlbmVyLW1hbnVmYWN0dXJpbmcvZGlzY3Vzc2lvbi8zNDAwNg0KZHVwbGljYXRlX2NvbHVtbiA8LSBjKCkNCmZvcihpIGluIGR1cGxpY2F0ZWQodCh0cmFpbikpKXsNCiAgZHVwbGljYXRlX2NvbHVtbiA8LSBjKGR1cGxpY2F0ZV9jb2x1bW4saSkNCn0NCg0KZHVwbGljYXRlX2NvbHVtbiA8LSBkdXBsaWNhdGVfY29sdW1uWzExOmxlbmd0aChkdXBsaWNhdGVfY29sdW1uKV0NCg0Kc3VtbWFyeV9yZXN1bHRzJGR1cGxpY2F0ZV9jb2x1bW4gPC0gZHVwbGljYXRlX2NvbHVtbg0KDQpzdW1tYXJ5X3Jlc3VsdHNfZGVjcmVhc2luZyA8LSBzdW1tYXJ5X3Jlc3VsdHNbb3JkZXIoLU5fMSksXQ0KDQpzdW1tYXJ5X3Jlc3VsdHMNCnN1bW1hcnlfcmVzdWx0c19kZWNyZWFzaW5nDQpgYGANCjxicj4NCg0KIyMjIyAgTGlzdCBvZiBEdXBsaWNhdGVkIENvbHVtbnMNCmBgYHtyfQ0Kc3VtbWFyeV9yZXN1bHRzX2RlY3JlYXNpbmdbKHN1bW1hcnlfcmVzdWx0c19kZWNyZWFzaW5nJGR1cGxpY2F0ZV9jb2x1bW49PVRSVUUpLF0NCmBgYA0KPGJyPg0KDQoNCg==